// for Emacs -*- c++ -*-

#ifndef _EVENTPROCESSOR_H_
#define _EVENTPROCESSOR_H_

#include "DistributedCounter.h"
#include "Numa.h"
/** if Event processing debuging is needed uncomment the followint */

//#define DEBUG_EVPROC

// forward definitions
class EventProcessorImp; // implementation of the event processor
class Message; // forward definition of all messages

/** Base class to implement all the front classes of event processors.
    
    These are the only classes that can construct the real EventProcessors.

    When a new EventProcessor is designed, a class should be derived
    from this base class and the constructor should just build the object.

    WARNING1: derived interface classes should not redefine any of the
    methods (including the destructor) except for defining a
    constructor with the same arguments as the real EventProcessor.

    In order to allow for simple manipulation of objects
    
*/


class EventProcessor {
private:
  // ensure these objects cannot be copied with default behavior
  EventProcessor(EventProcessor&);
  EventProcessor& operator =(const EventProcessor&);

  // special constructor for EventProcessorImp to create a interface object for itself
  EventProcessor(EventProcessorImp*);
  
protected:
  EventProcessorImp* evProc; // this is the real event Processor
  DistributedCounter* numCopies; // keep track of how many compies of
			       // this object are in the system. Only
			       // the last copy is allowed to destroy
			       // the object.
  bool noDelete; // should we delete the evProc in the destructor?

public:
  // constructor. We do not mimic the constructor of EventProcessorImp
  // since that class never gets directly instantiated
  // we provide this constrctor so that EventProcessors that
  // do nothing can be build so that they can be placed in containers and Swapped into
  EventProcessor(void);

  // method to check the validity of the Event Processor
	bool IsValid(void){ return evProc!=NULL; }

  // This method is called in the thread running the writer
  // All the other methods in EventProcessor run in a separate thread
  // The message results in putting the message in the message queue
  // Thread safety is ensured by the queue so there is no problem with simultaneous execution
  void ProcessMessage(Message& msg);
 

  // this method creates another thread running the main event processing loop
  // if the return false, than no thread was started
  // since the maximum number of threads allowed by this event is already reached
	//
	// If node is provided, it pins down the processor to the specified
	// node To avoid overly complicated scenarios, the node number is
	// wrapped around That means that if there are only 4 nodes,
	// specifying value 7 is the same as 3 (7 % 4).
	// Since the application
	// 
  // WARNING: this method only starts one thread, not all the allowed threads
  // it has to be executed repeteadly to start multiple threads

  bool ForkAndSpin(int node=NUMA_ALL_NODES);

  // When this functin is called, the thread calling it blocks until the event 
  // processor gets the Die message. This is useful to write main programs that 
  // wait for the whole thing to finish
  void WaitForProcessorDeath(void);

  ////////////////////////////////
  // Swapping paradigm interface
  
  // swap the content with anothe EventProcessor
  void Swap(EventProcessor&);
  
  // copy the content from another EventProcessor
  void CopyFrom(EventProcessor&);
  

  // destructor. Not virtual since we cannot add functionality  in derived classes
  ~EventProcessor();

  friend class EventProcessorImp; // we need this to give EventProcessorImp access to 
  // the constructor EventProcessor(EventProcessorImp*)
};


#endif // _EVENTPROCESSOR_H_
